﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Threading;
using Ranet.Olap.Core.DataDescription;
using Galaktika.BI.Silverlight.Controls.PivotGrid.View;
using Galaktika.BI.Silverlight.Controls.PivotGrid.Editors;
using Galaktika.BI.Silverlight.Controls.PivotGrid.Data;
using Galaktika.BI.Silverlight.Controls.PivotGrid.Data.Providers;
using Galaktika.BI.Charting;
using Galaktika.BI.Charting.PivotChart;
using Galaktika.BI.Silverlight.Controls.General;
using Galaktika.BI.Extensibility.Dom;
using Galaktika.BI.Runtime.Services;

namespace Galaktika.BI.Silverlight.Controls.PivotGrid.Controls
{
    public partial class CellsAreaControl : UserControl
    {
        protected readonly PivotGridPanel PivotGrid = null;
        private CellSetDataProvider m_Provider = null;
        private CellControlsCache m_Cache;

        public CellsAreaControl(PivotGridPanel grid)
        {
            InitializeComponent();

            IsTabStop = true;

            if (grid == null)
                throw new ArgumentNullException("grid");
            PivotGrid = grid;

            m_Cache = new CellControlsCache();

            this.MouseLeftButtonDown += new MouseButtonEventHandler(SpanCellsAreaControl_MouseLeftButtonDown);
            this.KeyDown += new KeyEventHandler(SpanCellsAreaControl_KeyDown);
            this.GotFocus += new RoutedEventHandler(SpanCellsAreaControl_GotFocus);
        }

        private CustomList<ActionInfo> m_ContextActionInfo = null;
        /// <summary>
        /// Контекстные действия
        /// </summary>
        public CustomList<ActionInfo> ContextActionInfo
        {
            get
            {
                return m_ContextActionInfo;
            }
            set
            {
                m_ContextActionInfo = value;
            }
        }

        void SpanCellsAreaControl_GotFocus(object sender, RoutedEventArgs e)
        {
            
        }

        private bool IsNumericKey(Key key)
        {
            switch (key)
            { 
                case Key.NumPad0:
                case Key.NumPad1:
                case Key.NumPad2:
                case Key.NumPad3:
                case Key.NumPad4:
                case Key.NumPad5:
                case Key.NumPad6:
                case Key.NumPad7:
                case Key.NumPad8:
                case Key.NumPad9:
                case Key.Decimal:
                case Key.Add:
                case Key.Subtract:
                case Key.D0:
                case Key.D1:
                case Key.D2:
                case Key.D3:
                case Key.D4:
                case Key.D5:
                case Key.D6:
                case Key.D7:
                case Key.D8:
                case Key.D9:
                    return true;
            }
            return false;
        }

        void SpanCellsAreaControl_KeyDown(object sender, KeyEventArgs e)
        {
            // Навигацию по ячейкам реализуем сами. Для того чтобы событие не шло дальше к скроллерам e.Handled = true;
            switch (e.Key)
            {
                case Key.Up:
                case Key.Down:
                case Key.Left:
                case Key.Right:
                case Key.PageUp:
                case Key.PageDown:
                case Key.Home:
                case Key.End:
                    e.Handled = true;
                    break;
            }

            if (FocusedCell != null)
            {
                if (!FocusedCell.IsEditing && IsNumericKey(e.Key))
                {
                    // Начинаем редактирование, чистим значение если есть
                    BeginEdit(true);
                    return;
                }

                CellControl currentCell = FocusedCell;

                // Заканчиваем редактирование 
                switch (e.Key)
                {
                    case Key.Up:
                    case Key.Down:
                    case Key.Enter:
                    case Key.Left:
                    case Key.Right:
                    case Key.PageUp:
                    case Key.PageDown:
                    case Key.Home:
                    case Key.End:
                        EndEdit();
                        break;
                    case Key.Escape:
                        CancelEdit();
                        break;
                    case Key.F2:
                        BeginEdit();
                        return;
                }

                CellControl cell = null;
                // Навигация
                if (LayoutRoot.ColumnDefinitions.Count > 0 &&
                    LayoutRoot.RowDefinitions.Count > 0)
                {
                    int colIndex = Grid.GetColumn(FocusedCell);
                    int rowIndex = Grid.GetRow(FocusedCell);

                    switch (e.Key)
                    {
                        case Key.Up:
                            rowIndex--;
                            break;
                        case Key.Down:
                        case Key.Enter:
                            rowIndex++;
                            break;
                        case Key.Left:
                            colIndex--;
                            break;
                        case Key.Right:
                            colIndex++;
                            break;
                        case Key.PageUp:
                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                            {
                                FocusedCell = GetFirstVertCell(FocusedCell);
                                return;
                            }
                            else
                            {
                                Rect rect = PivotGrid.CellsAreaBounds;
                                CellControl firstFullVisibleCell = GetFirstFullVisibleVertCell(FocusedCell, rect);
                                cell = firstFullVisibleCell;
                                if (firstFullVisibleCell != null)
                                {
                                    // Если первая полностью видимая (по высоте) ячейка совпадает с исходной, то это значит что ячейка первая на странице
                                    if (currentCell == firstFullVisibleCell)
                                    {
                                        CellControl prevCell = GetPrevVertCell(firstFullVisibleCell);
                                        cell = prevCell;
                                        if (prevCell != firstFullVisibleCell)
                                        {
                                            // Скроллируемся на страницу вверх
                                            PivotGrid.PageUp();
                                            // Видимая область
                                            rect = PivotGrid.CellsAreaBounds;
                                            // Получаем первую полностью видимую ячейку
                                            firstFullVisibleCell = GetFirstFullVisibleVertCell(prevCell, rect);
                                            // Смещаем скроллер на верхнюю границу ячейки
                                            if (firstFullVisibleCell != null)
                                            {
                                                PivotGrid.ScrollVerticalOffsetTo(GetCellPosition(firstFullVisibleCell).Y);
                                            }
                                            cell = firstFullVisibleCell;
                                        }
                                    }
                                }
                            }
                            break;
                        case Key.PageDown:
                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                            {
                                FocusedCell = GetLastVertCell(FocusedCell);
                                return;
                            }
                            else 
                            {
                                Rect rect = PivotGrid.CellsAreaBounds;
                                CellControl lastFullVisibleCell = GetLastFullVisibleVertCell(FocusedCell, rect);
                                cell = lastFullVisibleCell;
                                if (lastFullVisibleCell != null)
                                {
                                    // Если последняя полностью видимая (по высоте) ячейка совпадает с исходной, то это значит что ячейка последняя на странице
                                    if (currentCell == lastFullVisibleCell)
                                    {
                                        CellControl nextCell = GetNextVertCell(lastFullVisibleCell);
                                        cell = nextCell;
                                        if (nextCell != lastFullVisibleCell)
                                        {
                                            PivotGrid.ScrollVerticalOffsetTo(GetCellPosition(nextCell).Y);

                                            // Видимая область
                                            rect = PivotGrid.CellsAreaBounds;
                                            // Получаем последнюю полностью видимую ячейку
                                            lastFullVisibleCell = GetLastFullVisibleVertCell(nextCell, rect);

                                            cell = lastFullVisibleCell;
                                        }
                                    }
                                }
                            }
                            break;
                        case Key.Home:
                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                            {
                                // Перемещение на первую ячейку (крайняя левая верхняя).
                                cell = GetFirstCell();
                            }
                            else
                            {
                                cell = GetFirstHorzCell(currentCell);
                            }
                            break;
                        case Key.End:
                            if ((Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control)
                            {
                                // Перемещение на последнюю ячейку (крайняя правая нижняя).
                                cell = GetLastCell();
                            }
                            else
                            {
                                cell = GetLastHorzCell(currentCell);
                            }
                            break;

                    }

                    if (cell == null)
                    {
                        // Индекс не может быть меньше 0
                        colIndex = Math.Max(0, colIndex);
                        rowIndex = Math.Max(0, rowIndex);

                        // Индекс не может быть больше чем доступно
                        colIndex = Math.Min(colIndex, LayoutRoot.ColumnDefinitions.Count - 1);
                        rowIndex = Math.Min(rowIndex, LayoutRoot.RowDefinitions.Count - 1);

                        cell = m_Cache[colIndex, rowIndex];
                    }

                    FocusedCell = cell;
                }
            }
        }

        /// <summary>
        ///  Крайняя верхняя левая
        /// </summary>
        /// <returns></returns>
        public CellControl GetFirstCell()
        {
            int realColumnIndex = 0;
            int realRowIndex = 0;
            
            return m_Cache[realColumnIndex, realRowIndex];
        }

        /// <summary>
        /// Крайняя правая нижняя
        /// </summary>
        /// <returns></returns>
        public CellControl GetLastCell()
        {
            if (PivotGrid.ColumnsControl.LovestMemberControls.Count > 0 &&
                PivotGrid.RowsControl.LovestMemberControls.Count > 0)
            {
                return m_Cache[PivotGrid.ColumnsControl.LovestMemberControls.Count - 1,
                                PivotGrid.RowsControl.LovestMemberControls.Count - 1];
            }
            return null;
        }

        private CellControl GetFirstHorzCell(CellControl cell)
        {
            CellControl res = null;
            if (cell != null && cell.RowIndex > -1 && PivotGrid.ColumnsControl.LovestMemberControls.Count > 0)
            {
                res = m_Cache[0, cell.RowIndex];
            }
            return res;
        }

        private CellControl GetLastHorzCell(CellControl cell)
        {
            CellControl res = null;
            if (cell != null && cell.RowIndex > -1 && PivotGrid.ColumnsControl.LovestMemberControls.Count > 0)
            {
                res = m_Cache[PivotGrid.ColumnsControl.LovestMemberControls.Count - 1, cell.RowIndex];
            }
            return res;
        }

        private CellControl GetFirstVertCell(CellControl cell)
        {
            CellControl res = null;
            if (cell != null && cell.ColumnIndex > -1 && PivotGrid.RowsControl.LovestMemberControls.Count > 0)
            {
                res = m_Cache[cell.ColumnIndex, 0];
            }
            return res;
        }

        private CellControl GetLastVertCell(CellControl cell)
        {
            CellControl res = null;
            if (cell != null && cell.ColumnIndex > -1 && PivotGrid.RowsControl.LovestMemberControls.Count > 0)
            {
                res = m_Cache[cell.ColumnIndex, PivotGrid.RowsControl.LovestMemberControls.Count - 1];
            }
            return res;
        }

        public CellControl GetPrevVertCell(CellControl cell)
        {
            if (cell != null && cell.ColumnIndex > -1 && cell.RowIndex > -1)
            {
                if (cell.RowIndex > 0)
                {
                    return m_Cache[cell.ColumnIndex, cell.RowIndex - 1];
                }
                else 
                {
                    return cell;
                }
            }
            return null;
        }

        public CellControl GetNextVertCell(CellControl cell)
        {
            if (cell != null && cell.ColumnIndex > -1 && cell.RowIndex > -1)
            {
                int rowIndex = cell.RowIndex + 1;
                if (rowIndex < PivotGrid.RowsControl.LovestMemberControls.Count)
                {
                    return m_Cache[cell.ColumnIndex, rowIndex];
                }
                else
                {
                    return cell;
                }
            }
            return null;
        }

        public CellControl GetFirstFullVisibleVertCell(CellControl cell, Rect bounds)
        {
            if (bounds == null)
                return cell;

            if (cell != null && cell.ColumnIndex > -1 && cell.RowIndex > -1)
            {
                int rowIndex = cell.RowIndex;
                CellControl visibleCell = cell;
                CellControl prevCell = cell;
                if (rowIndex >= 0)
                {
                    Rect visibleBounds = Rect.Empty;
                    Rect cellBounds = Rect.Empty;
                    do
                    {
                        visibleBounds = Rect.Empty;
                        cellBounds = Rect.Empty;

                        prevCell = visibleCell;
                        rowIndex--;
                        if (rowIndex >= 0)
                        {
                            // Ячейка, которую будем проверять на видимость
                            visibleCell = m_Cache[cell.ColumnIndex, rowIndex];
                            if(visibleCell != null)
                            {
                                cellBounds = new Rect(GetCellPosition(visibleCell), new Size(visibleCell.ActualWidth, visibleCell.ActualHeight));        
                            }

                            // Рассчитываем какая часть ячейки попадает в заданную область
                            visibleBounds = cellBounds;
                            visibleBounds.Intersect(bounds);
                        }
                        else
                        {
                            break;
                        }
                    } while (visibleBounds != Rect.Empty && 
                        cellBounds != Rect.Empty &&
                        visibleBounds.Top == cellBounds.Top &&
                        visibleBounds.Height == cellBounds.Height);
                    return prevCell;
                }
            }
            return null;
        }

        public CellControl GetLastFullVisibleVertCell(CellControl cell, Rect bounds)
        {
            if (bounds == null)
                return cell;

            if (cell != null && cell.ColumnIndex > -1 && cell.RowIndex > -1)
            {
                int rowIndex = cell.RowIndex;
                CellControl visibleCell = cell;
                CellControl prevCell = cell;
                if (rowIndex >= 0)
                {
                    Rect visibleBounds = Rect.Empty;
                    Rect cellBounds = Rect.Empty;
                    do
                    {
                        visibleBounds = Rect.Empty;
                        cellBounds = Rect.Empty;

                        prevCell = visibleCell;
                        rowIndex++;
                        if (rowIndex < PivotGrid.RowsControl.LovestMemberControls.Count)
                        {
                            // Ячейка, которую будем проверять на видимость
                            visibleCell = m_Cache[cell.ColumnIndex, rowIndex];
                            if (visibleCell != null)
                            {
                                cellBounds = new Rect(GetCellPosition(visibleCell), new Size(visibleCell.ActualWidth, visibleCell.ActualHeight));
                            }

                            // Рассчитываем какая часть ячейки попадает в заданную область
                            visibleBounds = cellBounds;
                            visibleBounds.Intersect(bounds);
                        }
                        else
                        {
                            break;
                        }
                    } while (visibleBounds != Rect.Empty &&
                        cellBounds != Rect.Empty &&
                        visibleBounds.Top == cellBounds.Top &&
                        visibleBounds.Height == cellBounds.Height);
                    return prevCell;
                }
            }
            return null;
        }

        // Собственно редактор ячейки
        ICustomCellEditor m_CellEditor = null;
        ICustomCellEditor CellEditor
        {
            get {
                if (m_CellEditor == null)
                {
                    m_CellEditor = new TextBoxCellEditor();
                    m_CellEditor.PivotGridEditorCancelEdit += new EventHandler(CellEditor_PivotGridEditorCancelEdit);
                    m_CellEditor.PivotGridEditorEndEdit += new EventHandler(CellEditor_PivotGridEditorEndEdit);
                }
                return m_CellEditor;
            }
        }

        void CellEditor_PivotGridEditorEndEdit(object sender, EventArgs e)
        {
            EndEdit();

            KeyEventArgs arg = e as KeyEventArgs;
            if (arg != null && arg.Key == Key.Enter)
            {
                this.SpanCellsAreaControl_KeyDown(this, arg);
            }
        }

        void CellEditor_PivotGridEditorCancelEdit(object sender, EventArgs e)
        {
            CancelEdit();            
        }

        /// <summary>
        /// Применяет изменения, внесенные в контрол редактирования
        /// </summary>
        internal void EndEdit()
        {
            // Проверяем что редактирование в принципе начато на данный момент
            if (FocusedCell != null && FocusedCell.IsEditing)
            {
                FocusedCell.IsEditing = false;

                if (m_CellEditor != null && FocusedCell.Cell != null)
                {
                    LayoutRoot.Children.Remove(m_CellEditor.Editor);

                    if (CellEditor.Value == null || String.IsNullOrEmpty(CellEditor.Value.ToString()))
                            return;

                    // Проверяем, что произошло изменение значения
                    if (FocusedCell.Cell.CellDescr.Value != null && FocusedCell.Cell.CellDescr.Value.Value != null)
                    {
                        if (FocusedCell.Cell.CellDescr.Value.Value.ToString() == CellEditor.Value.ToString())
                            return;
                    }

                    // В качестве разделителя для числа обязательно должна использоватьеся точка (т.к. эта строка будет помещена в МDX)
                    String value = CellEditor.Value.ToString();
                    value = value.Replace(System.Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.CurrencyDecimalSeparator, ".");
                    RaiseCellValueChanged(FocusedCell.Cell, value);

                }
            }

            this.Focus();
        }

        public event CellValueChangedEventHandler CellValueChanged;
        private void RaiseCellValueChanged(CellView cell, String newValue)
        {
            if (cell == null)
                return;

            CellValueChangedEventHandler handler = this.CellValueChanged;
            if (handler != null)
            {
                IDictionary<String, MemberInfo> tuple = cell.GetTuple();
                handler(this, new CellValueChangedEventArgs(this, cell, newValue, tuple.Values.ToList()));
            }
        }

        private void BeginEdit()
        {
            BeginEdit(false);
        }

        public Point GetCellPosition(CellControl cell)
        {
            Point point = new Point(0, 0);

            if (cell != null)
            {
                Point transformPoint = this.LayoutRoot.TransformToVisual(cell).Transform(point);
                return new Point(transformPoint.X * -1, transformPoint.Y * -1);
            }

            return point;
        }

        private void BeginEdit(bool clearCellValue)
        {
            // TODO: Редактирование наверное не надо начинать пока идет запись предыдущей
            //if (PivotGrid.SpanPivotGrid.IsWaiting)
            //    return;

            if (FocusedCell != null && FocusedCell.Cell != null && FocusedCell.Cell.IsUpdateable)
            {
                if (!clearCellValue && FocusedCell.Cell.CellDescr != null &&
                    FocusedCell.Cell.CellDescr.Value != null)
                {
                    CellEditor.Value = FocusedCell.Cell.CellDescr.Value.DisplayValue;
                }
                else 
                {
                    CellEditor.Value = String.Empty;
                }

                if (FocusedCell.ColumnIndex > -1 && FocusedCell.RowIndex > -1)
                {
                    if (!LayoutRoot.Children.Contains(CellEditor.Editor))
                    {
                        LayoutRoot.Children.Add(CellEditor.Editor);
                    }

                    Grid.SetColumn(CellEditor.Editor, FocusedCell.ColumnIndex);
                    Grid.SetRow(CellEditor.Editor, FocusedCell.RowIndex);
                }

                CellEditor.Editor.Focus();

                FocusedCell.IsEditing = true;
            }
        }

        internal void CancelEdit()
        {
            // Проверяем что редактирование в принципе начато на данный момент
            if (FocusedCell != null)
            {
                FocusedCell.IsEditing = false;

                if (m_CellEditor != null)
                {
                    LayoutRoot.Children.Remove(m_CellEditor.Editor);
                }
            }

            this.Focus();
        }

        void SpanCellsAreaControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
            //this.PivotGrid.FUCK();
            this.Focus();
            Point pos = e.GetPosition(this.LayoutRoot);
        }

        Dictionary<MemberControl, ColumnDefinition> m_Columns = new Dictionary<MemberControl, ColumnDefinition>();
        Dictionary<MemberControl, RowDefinition> m_Rows = new Dictionary<MemberControl, RowDefinition>();

        public void Intialize(CellSetDataProvider cs_provider)
        {
            // Старая сфокусированная ячейка
            CellControl oldFocusedCell = FocusedCell;

            m_Cache = new CellControlsCache();
            m_Provider = cs_provider;
            m_Columns.Clear();
            m_Rows.Clear();

            LayoutRoot.Children.Clear();
            LayoutRoot.ColumnDefinitions.Clear();
            LayoutRoot.RowDefinitions.Clear();

            if (m_Provider == null)
                return;

            int columnIndex = 0;
            foreach (MemberControl columnCtrl in PivotGrid.ColumnsControl.LovestMemberControls)
            {
                columnCtrl.SizeChanged += new SizeChangedEventHandler(columnCtrl_SizeChanged);
                
                if (!m_Columns.ContainsKey(columnCtrl))
                {
                    ColumnDefinition current_column = new ColumnDefinition();
                    LayoutRoot.ColumnDefinitions.Add(current_column);
                    m_Columns.Add(columnCtrl, current_column);
                }

                int rowIndex = 0;
                foreach (MemberControl rowCtrl in PivotGrid.RowsControl.LovestMemberControls)
                {
                    rowCtrl.SizeChanged += new SizeChangedEventHandler(rowCtrl_SizeChanged);
                    
                    if (!m_Rows.ContainsKey(rowCtrl))
                    {
                        RowDefinition current_row = new RowDefinition();
                        LayoutRoot.RowDefinitions.Add(current_row);
                        m_Rows.Add(rowCtrl, current_row);
                    }

                    CellDescription cell_descr = m_Provider.GetCellDescription(columnIndex, rowIndex);
                    CellView cellView = new CellView(cell_descr, columnCtrl.Member, rowCtrl.Member, m_Provider.GetInvisibleCoords(columnIndex, rowIndex));
                    CellControl cellControl = new CellControl(cellView, columnIndex, rowIndex);

                    m_Cache.Add(cellControl, columnIndex, rowIndex);
                    

                    cellControl.MouseLeftButtonDown += new MouseButtonEventHandler(cellControl_MouseLeftButtonDown);
                    cellControl.ShowContextMenu += new EventHandler<CellClickEventArgs>(OnShowContextMenu);

                    LayoutRoot.Children.Add(cellControl);
                    Grid.SetColumn(cellControl, columnIndex);
                    Grid.SetRow(cellControl, rowIndex);

                    rowIndex++;
                }
                columnIndex++;
            }

            // Пытаемся получить ячейку на которую хотим установить фокус
            if (oldFocusedCell != null)
            {
                CellControl cell_ctrl = m_Cache[oldFocusedCell.ColumnIndex, oldFocusedCell.RowIndex];
                if (cell_ctrl != null && cell_ctrl.Cell != null &&
                    cell_ctrl.Cell.ColumnMember != null && oldFocusedCell.Cell.ColumnMember != null &&
                    cell_ctrl.Cell.RowMember != null && oldFocusedCell.Cell.RowMember != null &&
                    cell_ctrl.Cell.ColumnMember.UniqueName == oldFocusedCell.Cell.ColumnMember.UniqueName &&
                    cell_ctrl.Cell.RowMember.UniqueName == oldFocusedCell.Cell.RowMember.UniqueName)
                {
                    this.Focus();
                    FocusedCell = cell_ctrl;
                }
                else
                {
                    SetDefaultFocus();
                }
            }
            else
            {
                SetDefaultFocus();
            }
        }

        CustomContextMenu m_ContextMenu = null;
        public CustomContextMenu ContextMenu
        {
            get
            {
                if (m_ContextMenu == null)
                {
                    m_ContextMenu = new CustomContextMenu();
                    if (ContextActionInfo != null && ContextActionInfo.Count > 0)
                    {
                        if (m_ContextMenu.Items.Count > 0)
                        {
                            m_ContextMenu.AddMenuSplitter();
                        }

                        foreach (ActionInfo info in ContextActionInfo)
                        {
                            ContextMenuItem item = new ContextMenuItem(info.ACaption);
                            item.ItemClick += new EventHandler(item_ItemClick);
                            item.Tag = info;
                            item.Icon = UriResources.Images.ActionNode16;
                            m_ContextMenu.AddMenuItem(item);
                        }
                    }
                }
                return m_ContextMenu;
            }
        }

        void item_ItemClick(object sender, EventArgs e)
        {
            ContextMenuItem item = sender as ContextMenuItem;
            if (item != null && item.Tag != null)
            {
                if (item.Tag is ActionInfo)
                {
                    ActionInfo ai = item.Tag as ActionInfo;
                    if (ai != null && ai.AActionInvoker != null && ((BrickActionInvoker)ai.AActionInvoker).Action != null)
                    {
                        List<ArgumentEntry> args = new List<ArgumentEntry>(((BrickActionInvoker)ai.AActionInvoker).Parameters);

                        // Формируем параметры для вызываемого экшена.
                        // Выбранных ячеек может быть несколько и для каждой из них нужно передать тапл
                        // Поэтому ключом будет число от 0 до ......
                        // значением будет сериализованный список строк

                        //RaiseLogMessage("Execute Context Action: " + ((BrickActionInvoker)ai.AActionInvoker).Action.Name);

                        String cubeName = String.Empty;
                        String connectionString = String.Empty;
                        if (PivotGrid.CellSetProvider != null && PivotGrid.CellSetProvider.CellSet_Description != null)
                        {
                            cubeName = PivotGrid.CellSetProvider.CellSet_Description.CubeName;
                            connectionString = PivotGrid.CellSetProvider.CellSet_Description.ConnectionString;
                        }

                        int key = 0;

                        args.Add(new ArgumentEntry("CUBE_NAME", cubeName));
                        args.Add(new ArgumentEntry("CONNECTION_STRING", connectionString));

                        CellView cell = ContextMenu.Tag as CellView;
                        if (cell != null)
                        {
                            List<MemberInformation> str_tuple = new List<MemberInformation>();
                            IDictionary<String, MemberInfo> tuple = cell.GetTuple();
                            foreach (KeyValuePair<String, MemberInfo> kp in tuple)
                            {
                                if (kp.Value != null)
                                {
                                    String uniqName = kp.Value.UniqueName;
                                    str_tuple.Add(new MemberInformation(kp.Key, uniqName));
                                }
                            }

                            args.Add(new ArgumentEntry(key.ToString(), XmlUtility.Obj2XmlStr(str_tuple, "")));
                        }

                        ScriptEngine.Execute(new MockCaller(this.PivotGrid.SpanPivotGrid.Owner.Context), ((BrickActionInvoker)ai.AActionInvoker).Action, args);
                    }
                    return;
                }
            }
        }

        void OnShowContextMenu(object sender, CellClickEventArgs args)
        {
            if (ContextMenu.IsDropDownOpen)
                ContextMenu.IsDropDownOpen = false;

            ContextMenu.SetLocation(args.Position);
            ContextMenu.Tag = args.Cell;
            ContextMenu.IsDropDownOpen = true;
        }

        private void SetDefaultFocus()
        {
            this.Focus();
            FocusedCell = m_Cache[0, 0];
        }

        private CellControl m_FocusedCell = null;
        public CellControl FocusedCell
        {
            get { return m_FocusedCell; }
            set
            {
                if (m_FocusedCell != value)
                {
                    CellControl old_focusedCell = m_FocusedCell;
                    if (m_FocusedCell != null)
                    {
                        EndEdit();
                        m_FocusedCell.IsFocused = false;
                    }
                    
                    m_FocusedCell = value;

                    if (m_FocusedCell != null)
                    {
                        m_FocusedCell.IsFocused = true;
                    }

                    RaiseFocusedCellChanged(old_focusedCell, m_FocusedCell);
                }
            }
        }

        public event FocusedCellChangedEventHandler FocusedCellChanged;
        private void RaiseFocusedCellChanged(CellControl oldFocusedCell, CellControl newFocusedCell)
        {
            FocusedCellChangedEventHandler handler = this.FocusedCellChanged;
            if (handler != null)
            {
                handler(this, new FocusedCellChangedEventArgs(this, oldFocusedCell, newFocusedCell));
            }
        }

        void cellControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            FocusedCell = sender as CellControl;
        }

        void rowCtrl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            MemberControl ctrl = sender as MemberControl;
            if (ctrl != null && e.NewSize.Height.CompareTo(double.NaN) != 0)
            { 
                if(m_Rows.ContainsKey(ctrl))
                {
                    //m_Rows[ctrl].Height = new GridLength(e.NewSize.Height);
                    m_Rows[ctrl].Height = new GridLength(ctrl.Row.ActualHeight);
                }
            }
        }

        void columnCtrl_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            MemberControl ctrl = sender as MemberControl;
            if (ctrl != null && e.NewSize.Width.CompareTo(double.NaN) != 0)
            {
                if (m_Columns.ContainsKey(ctrl))
                {
                    //m_Columns[ctrl].Width = new GridLength(e.NewSize.Width);
                    m_Columns[ctrl].Width = new GridLength(ctrl.Column.ActualWidth);
                }
            }
        }
    }
}
